package com.swsc.solarverse.component.redis;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @Author chencl
 * @Date 2022/9/25 14:20
 * @Version 1.0
 * @Description
 */
@Slf4j
@Service
public class StringRedisService {
    private final StringRedisTemplate stringRedisTemplate;

    public StringRedisService(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    public void set(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    public String get(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }

    public void setEx(String key, String value, long expire) {
        stringRedisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
    }

    public boolean setExpire(String key, long timeout) {
        return stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
    }

    public long getExpire(String key) {
        return stringRedisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    public boolean checkExist(String key) {
        return stringRedisTemplate.hasKey(key);
    }

    public boolean del(String key) {
        log.info("delete redis key => {}", key);
        return stringRedisTemplate.delete(key);
    }

    public Boolean nxLock(String key, String value, long timeout) {
        return stringRedisTemplate.opsForValue().setIfAbsent(key, value, timeout, TimeUnit.SECONDS);
    }

    public void nxUnlock(String key) {
        stringRedisTemplate.delete(key);
    }

    public boolean luaLock(String key, String value, long timeout) {
        // timeout: 秒
        try {
            //加锁成功返回 true，加锁失败返回 fasle。效果等同于 redisTemplate.opsForValue().setIfAbsent
            String luaScript = "if redis.call('set', KEYS[1], ARGV[1], 'NX', 'EX', ARGV[2]) then return 1 else return 0 end";
            org.springframework.data.redis.core.script.RedisScript<Long> redisScript = new org.springframework.data.redis.core.script.DefaultRedisScript<>(luaScript, Long.class);
            Long result = stringRedisTemplate.execute(redisScript, java.util.Collections.singletonList(key), value, String.valueOf(timeout));

            return result != null && result == 1;
        } catch (Exception e) {
            // Handle exceptions
            return false;
        }
    }

    public void luaUnlock(String key, String value) {
        try {
            //拿到锁的线程才可以释放锁，lockValue 可以设置为 uuid。
            String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            org.springframework.data.redis.core.script.RedisScript<Long> redisScript = new org.springframework.data.redis.core.script.DefaultRedisScript<>(luaScript, Long.class);
            stringRedisTemplate.execute(redisScript, java.util.Collections.singletonList(key), value);
        } catch (Exception e) {
            // Handle exceptions
        }
    }



}
